#include "head.h"
#define COLOR_CYAN    "\x1b[36m"  // 青蓝色
#define COLOR_RESET   "\x1b[0m"   // 默认颜色
#define COLOR_YELLOW  "\x1b[33m"  // 黄色

int printCmd(void) {
    printf("\n");
    printf("%s--------指令目录--------%s\n", COLOR_CYAN, COLOR_RESET);
    printf("%scd      pwd       ls%s\n", COLOR_CYAN, COLOR_RESET);
    printf("%sputs    gets      remove%s\n", COLOR_CYAN, COLOR_RESET);
    printf("%srmdir             mkdir%s\n", COLOR_CYAN, COLOR_RESET);
    printf("%s--------指令目录--------%s\n", COLOR_CYAN, COLOR_RESET);

    return 0;
}

// 如：，输入‘mkdir file’ -->  ‘file'
void remove_first_token(char *str) {
    // Find the end position of the first token
    int len = strlen(str);
    int i = 0;
    // 先找到第一个空格的位置，表示第一个单词的结束
    for (; i < len; i++) {
        if (str[i] == ' ') {
            break;
        }
    }
    // 然后跳过第一个单词的所有空格
    for (; i < len; i++) {
        if (str[i] != ' ') {
            break;
        }
    }
    // 将剩余部分向前移动，覆盖掉第一个单词和空格
    int j = 0;
    for (; i < len - 1; i++) {
        str[j++] = str[i];
    }
    // 这里已经把最后的换行符给移除了
    str[j++] = '\0';
    str[j] = '\0';
}

// 命令字符串转数字
 int trantoNum(char *p,int *num) {
     // printf("length_p = %d\n", length_p);
     if (strcmp(p, "cd") == 0) {
         *num = 0;
     } else if (strcmp(p, "ls") == 0){
         *num = 1;
     } else if (strcmp(p, "puts") == 0) {
         *num = 2;
     } else if (strcmp(p, "gets") == 0) {
         *num = 3;
     } else if (strcmp(p, "remove") == 0) {
         *num = 4;
     } else if (strcmp(p, "pwd") == 0) {
         *num = 5;
     } else if (strcmp(p, "mkdir") == 0) {
         *num = 6;
     } else if (strcmp(p, "rmdir") == 0) {
         *num = 7;
     } else if (strcmp(p, "quit") == 0) {
         *num = 8;
     }
     return 0;
 }


int removeLeadingSpaces(char* str) {
    // 使用两个指针 i 和 j ,i 用于遍历字符串，j 用于覆盖空格
    int i = 0, j = 0;
    while (str[i] == ' ') {
        i++;
    }
    // 如果字符串开头有空格，则将后续内容向前移动，覆盖空格
    if (i > 0) {
        while (str[i] != '\0') {
            str[j] = str[i];
            i++;
            j++;
        }
        str[j] = '\0'; // 最后在字符串末尾添加空字符 ‘\0’
        return 1; // 返回 1 表示成功删除空格
    }
    return 0; // 返回 0 表示没有空格可以删除
}
int main(int argc, char* argv[])
{
    system("clear"); // 清空屏幕
    // ./client ip port
    ARGS_CHECK(argc, 3); // 检查命令行参数
    int sockfd; 
    tcpInit(&sockfd,argv[1],argv[2]); // 初始化TCP连接，连接到服务器



    // 登录功能
    int ret_num = loginFunc(sockfd);
    if (ret_num == -1) return 0; // 若是登录失败（返回 -1 ），客户端退出！！！

    train_t train_command;

    while (1) {
        

        printf("\n:"); // 打印提示符 ：
        // fflush(stdout);
        // printf("this way sir\n");
        // 打印服务器发送来的消息，因为客户端与服务器端成功建立连接后
        //          并且客户端成功登录后，会构造用户的初始目录路径，会将当前工作目录消息发送给客户端
        //          客户端便会打印服务发送来的消息，即打印当前工作路径（/home/<Username>）
        print_network_message(sockfd); 
        // printf("i am here\n");
        printf("$ ");
        printf("\n");
        // 刷出输出缓冲区
        // 注意所有的输出，看看有没有刷出内容
        fflush(stdout);
        printCmd();
        // scanf
        // strtoken
        bzero(&train_command, sizeof(train_command));
        fgets(train_command.data, 4096, stdin); // 读取用户输入的命令

        // 这里是在是太关键了
        // 移除输入字符串开头的空格 
        // 假设 ls -l /home/user/files
        //   1、移除前导空格
        //   2、复制命令字符串  temp_data 变为 "ls -l /home/user/files"
        //   3、分割命令字符串  token 变为 ”ls“
        //   4、存储命令名称    fxxxk 变为 ”ls“
        //   5、移除第一个命令  train_command.data  变为 ”-l /hoem/user/files“
        //   6、计算命令长度    train_command.length 变为 16
        //   7、提取文件名      filename 变为 ”files“
        //   8、转换命令为编号  comType  变为 1
        removeLeadingSpaces(train_command.data);
        train_command.data[strlen(train_command.data) - 1] = ' ';
        train_command.data[strlen(train_command.data)] = ' ';
        // puts(train_command.data);
        // 创建一个临时数组 temp_data，并将 train_command.data的内容复制到temp_data中，
        //      这样做的目的是为了在后续处理中不改变原始的 train_command内容
        char temp_data[4096];
        strcpy(temp_data, train_command.data);
        
        // 使用strtok 风格命令字符串，提取命令类型（如mkdir）和参数（如 file）
        char *token;
        token = strtok(temp_data, " ");// 处理输入字符串，提取第一个命令单词
        // puts(token);
        // 用户输入 mkdir file -> file
        char fxxxk[1024];
        strcpy(fxxxk, token); // 将获取到的命令名称复制到 fxxxk 数组中，以便后续使用
        remove_first_token(train_command.data); // 移除 train_command.data中的第一个令牌及其后的控股个，如果train_command.data是“ls -l”，调用该函数后，字符串变为“-l""

        train_command.length = strlen(train_command.data);// 计算处理后的命令字符串的长度

        // 提取命令中的文件名，如果命令中包含路径（/），则提取最后一个/之后的部分作为文件
        char filename[256];
        char *filename_start = strrchr(train_command.data, '/');
        if (filename_start != NULL) { // 如果发现'/'，则文件名为'/'之后的内容
            filename_start++; // 跳过'/'，指向文件名的起始位置
        } else {
            filename_start = train_command.data; // 否则整个字符串都是文件名
        }

        strcpy(filename, filename_start); // 复制文件名到新的字符数组中
        filename[strlen(filename) - 1] = '\0';

        int comType = 999;
        trantoNum(fxxxk, &comType); // 将命令单词转换为命令编号
           // char *str0 = "cd";

        // 客户端将解析后的用户输入命令类型发送给服务器
        send(sockfd, &comType, sizeof(int), 0); 
        // 将解析后的用户输入命令命令参数（如 file）及长度发送给服务器
        send(sockfd,&train_command,sizeof(train_command.length)+train_command.length,0); 

        // 注意什么时候需要非阻塞的send
        int ifError;
        // comType = 8;
        // 根据comType的值调用相应的函数来处理命令
        switch (comType) {
        case 0:
            // 什么都没做
            cdFunc(sockfd);
            break;
        case 1:
            lsFunc(sockfd);
            break;
        case 2:
            putsFunc(sockfd, filename);
            break;
        case 3:
            printf("filename = %s\n", filename);
            // 这里先接收一个整数表示是否是报错信息
            getsFunc(sockfd, filename);
            break;
        case 4:
            removeFunc(sockfd);
            break;
        case 5:
            pwdFunc(sockfd);
            break;
        case 6:
            mkdirFunc(sockfd);
            break;
        case 7:
            rmdirFunc(sockfd);
            break;
        case 8:
            recv(sockfd, &ifError, sizeof(int), 0);
            return 0;
        default:
            // 
            recv(sockfd, &ifError, sizeof(int), 0);
            printf("No command found!\n");
        }
        // if (comType != -1) {

        //     int ifError;
        //     recv(sockfd, &ifError, sizeof(int), 0);
        //     if (ifError != 0) {
        //         // 接收一个小火车
        //         print_network_message(sockfd);
        //     }
        // }
    }

    close(sockfd);

    return 0;
}

